package com.webchat.pgc.service.mall;


import com.webchat.common.bean.APIPageResponseBean;
import com.webchat.common.constants.MessageCardConstants;
import com.webchat.common.enums.mall.MallReviewStatusEnum;
import com.webchat.common.enums.messagequeue.MessageBroadChannelEnum;
import com.webchat.common.service.messagequeue.producer.MessageQueueProducer;
import com.webchat.common.util.DateUtils;
import com.webchat.common.util.ThreadPoolExecutorUtil;
import com.webchat.domain.dto.messagecard.MessageCardSendDTO;
import com.webchat.domain.inter.mall.MallShopReviewInter;
import com.webchat.domain.vo.request.mall.ShopReviewRequestVO;
import com.webchat.domain.vo.response.UserBaseResponseInfoVO;
import com.webchat.domain.vo.response.mall.MallShopBaseVO;
import com.webchat.domain.vo.response.mall.MallShopResponseVO;
import com.webchat.domain.vo.response.mall.MallShopReviewResponseVO;
import com.webchat.domain.vo.response.sys.SysDataDictionaryBaseVO;
import com.webchat.pgc.config.MessageCardAccountConfig;
import com.webchat.pgc.config.MessageCardTemplateConfig;
import com.webchat.pgc.config.WebchatPageConfig;
import com.webchat.pgc.repository.dao.mall.IMallShopReviewDAO;
import com.webchat.pgc.repository.entity.mall.MallShop;
import com.webchat.pgc.repository.entity.mall.MallShopReview;
import com.webchat.pgc.service.AccountService;
import com.webchat.pgc.service.sys.SysDataDictionaryDetailService;
import com.webchat.pgc.service.sys.SysDataDictionaryService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static com.webchat.common.util.DateUtils.YYYY_MM_DD_HH_MM;

@Service
public class MallShopReviewService {

    @Autowired
    private IMallShopReviewDAO mallShopReviewDAO;

    @Autowired
    private MallShopService mallShopService;
    @Autowired
    private MallReviewerService mallReviewerService;
    @Autowired
    private MessageCardTemplateConfig messageCardTemplateConfig;
    @Autowired
    private MessageCardAccountConfig messageCardAccountConfig;
    @Autowired
    private AccountService accountService;
    @Autowired
    private WebchatPageConfig webchatPageConfig;
    @Autowired
    private MessageQueueProducer<MessageCardSendDTO, Long> messageQueueProducer;
    @Autowired
    private SysDataDictionaryService sysDataDictionaryService;
    @Autowired
    private SysDataDictionaryDetailService sysDataDictionaryDetailService;

    /**
     * 创建店铺信息审核订单
     *
     *
     * @param shop
     * @param userId
     * @return
     */
    public Long create(MallShop shop, String userId) {

        MallShopReview mallShopReview = new MallShopReview();
        mallShopReview.setShopId(shop.getId());
        mallShopReview.setReviewStatus(MallReviewStatusEnum.PENDING.getStatus());
        mallShopReview.setCreateBy(userId);
        mallShopReview.setCreateDate(new Date());
        mallShopReview = mallShopReviewDAO.save(mallShopReview);
        // 异步通知审核员（动态消息卡片），失败不阻塞住流程
        ThreadPoolExecutorUtil.execute(() -> doNotifyReviewerByIMCard(shop, userId));
        return mallShopReview.getId();
    }

    /**
     * 审核申请信息
     *
     * @return
     */
    @Transactional
    public boolean review(ShopReviewRequestVO requestVO) {

        MallReviewStatusEnum reviewStatusEnum = MallReviewStatusEnum.getByStatus(requestVO.getReviewStatus());
        Assert.notNull(reviewStatusEnum, "不支持的审核状态");

        Integer reviewStatus = requestVO.getReviewStatus();
        Long id = requestVO.getId();
        MallShopReview review = mallShopReviewDAO.findById(id).orElse(null);
        Assert.notNull(review, "审核失败：审核单不存在");
        review.setReviewStatus(reviewStatus);
        review.setReviewReason(requestVO.getReviewReason());
        // 更新review结果
        mallShopReviewDAO.save(review);
        // 通知店铺上下架
        mallShopService.updateStatusByReview(review.getShopId(), reviewStatusEnum);
        // 接入IM服务消息卡能力，通知商家审核结果
        ThreadPoolExecutorUtil.execute(() -> doNotifyShopMasterByIMCard(requestVO, review.getShopId(), review.getCreateBy()));
        return true;
    }

    public APIPageResponseBean<MallShopReviewResponseVO> page(String shopName, Integer reviewStatus,
                                                              Integer pageNo, Integer pageSize) {

        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, Sort.by(Sort.Direction.DESC, "id"));

        shopName = StringUtils.isNotBlank(shopName) ? shopName : null;
        Page<MallShopReviewInter> page = mallShopReviewDAO.page(shopName, reviewStatus, pageable);

        List<MallShopReviewResponseVO> vos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(page.getContent())) {
            List<MallShopReviewInter> entities = page.getContent();
            Set<Long> shopIdSet = entities.stream().map(MallShopReviewInter::getShopId).collect(Collectors.toSet());
            Set<String> createUserId = entities.stream().map(MallShopReviewInter::getCreateUserId).filter(Objects::nonNull).collect(Collectors.toSet());
            Set<String> updateUserId = entities.stream().map(MallShopReviewInter::getUpdateUserId).filter(Objects::nonNull).collect(Collectors.toSet());
            createUserId.addAll(updateUserId);
            Map<String, UserBaseResponseInfoVO> userMap = accountService.batchGet(createUserId);
            Map<Long, MallShopBaseVO> shopMap = mallShopService.batchGetMap(new ArrayList<>(shopIdSet));
            vos = entities.stream().map(e -> {
                MallShopReviewResponseVO vo = new MallShopReviewResponseVO();
                vo.setId(e.getId());
                vo.setShopId(e.getShopId());
                vo.setReviewStatus(e.getReviewStatus());
                vo.setReviewReason(e.getReviewReason());
                vo.setReviewTime(e.getReviewDate() != null ? e.getReviewDate().getTime() : null);
                vo.setSubmitTime(e.getSubmitDate() != null ? e.getSubmitDate().getTime() : null);
                vo.setReviewUser(e.getUpdateUserId() != null && !ObjectUtils.equals(e.getCreateUserId(), e.getUpdateUserId()) ? userMap.get(e.getUpdateUserId()) : null);
                vo.setSubmitUser(userMap.get(e.getCreateUserId()));
                vo.setShop(shopMap.get(e.getShopId()));
                return vo;
            }).toList();
        }
        return APIPageResponseBean.success(pageNo, pageSize, page.getTotalElements(), vos);
    }


    private void doNotifyShopMasterByIMCard(ShopReviewRequestVO requestVO,
                                            Long shopId, String userId) {
        // 1. 获取店铺信息
        MallShopResponseVO shop = mallShopService.detail(shopId);
        if (shop == null) {
            return;
        }
        boolean isAccept = MallReviewStatusEnum.APPROVED.getStatus().equals(requestVO.getReviewStatus());
        String templateId = isAccept ? messageCardTemplateConfig.getReviewAccept() : messageCardTemplateConfig.getReviewReject();
        // 获取数据字典
        Map<String, String> dataDictionary = getDataDictionary(MessageCardConstants.CODE);
        // 2. 构造消息卡
        MessageCardSendDTO messageCardSendDTO = new MessageCardSendDTO();
        messageCardSendDTO.setSender(messageCardAccountConfig.getMallReview());
        messageCardSendDTO.setTemplateId(templateId);
        messageCardSendDTO.setReceiver(userId);
        messageCardSendDTO.setTitle(dataDictionary.getOrDefault(
                MessageCardConstants.EnumerateValues.SHOP_REVIEW_RESULT_TITLE.getCode(),
                MessageCardConstants.EnumerateValues.SHOP_REVIEW_RESULT_TITLE.getDefaultValue())
        );
        messageCardSendDTO.setLogo(dataDictionary.getOrDefault(
                MessageCardConstants.EnumerateValues.WORK_ORDER_CARD_ICON.getCode(),
                MessageCardConstants.EnumerateValues.WORK_ORDER_CARD_ICON.getDefaultValue())
        );
        messageCardSendDTO.setRedirectName(dataDictionary.getOrDefault(
                MessageCardConstants.EnumerateValues.VIEW_REVIEW_RESULT_NAME.getCode(),
                MessageCardConstants.EnumerateValues.VIEW_REVIEW_RESULT_NAME.getDefaultValue())
        );
        messageCardSendDTO.setRedirectUrl(webchatPageConfig.getMallShopManage());

        // 静态数据赋值
        Map<String, String> varsParameter = new HashMap<>();
        varsParameter.put("logo", shop.getLogo());
        varsParameter.put("name", shop.getName());
        varsParameter.put("dateTime", DateUtils.getDate2String(YYYY_MM_DD_HH_MM, new Date()));
        varsParameter.put("reviewReason", requestVO.getReviewReason());
        // 动态数据赋值
        dataDictionary.forEach((k, v) -> {
                    if (!varsParameter.containsKey(v)) {
                        return;
                    }
                    dataDictionary.put(k, varsParameter.get(v));
                }
        );
        /*
         * 已弃用，改为从数据字典中获取变量值
         Map<String, Object> vars = new HashMap<>()
         vars.put("k1", "店铺LOGO")
         vars.put("k2", "店铺名")
         vars.put("k3", "审核时间")
         vars.put("v1", shop.getLogo())
         vars.put("v2", shop.getName())
         vars.put("v3", DateUtils.getDate2String(YYYY_MM_DD_HH_MM, new Date()))
         vars.put("reason", requestVO.getReviewReason())
         */

        messageCardSendDTO.setVars((Map) dataDictionary);
        // 3. 接入IM服务号推送
        /**
         * MQ广播通知connect服务，完成服务号消息卡内容websocket主动推送
         */
        messageQueueProducer.broadSend(MessageBroadChannelEnum.QUEUE_MESSAGE_CARD_PUSH, messageCardSendDTO);
    }

    /**
     * 给审核送实时推送审核消息卡片
     *
     * @param mallShop
     */
    private void doNotifyReviewerByIMCard(MallShop mallShop, String operator) {

        List<String> reviewers = mallReviewerService.getShopReviewers();
        if (CollectionUtils.isEmpty(reviewers)) {
            return;
        }

        // 获取提交人信息
        UserBaseResponseInfoVO submitUser = accountService.accountInfo(operator);
        // 获取数据字典
        Map<String, String> dataDictionary = getDataDictionary(MessageCardConstants.CODE);

        /**
         * 1. 构造动态消息
         */
        MessageCardSendDTO messageCardSendDTO = new MessageCardSendDTO();
        messageCardSendDTO.setSender(messageCardAccountConfig.getMallReview());
        messageCardSendDTO.setTemplateId(messageCardTemplateConfig.getWorkOrder());
        messageCardSendDTO.setReceivers(new HashSet<>(reviewers));
        messageCardSendDTO.setTitle(dataDictionary.getOrDefault(
                MessageCardConstants.EnumerateValues.SHOP_WORK_ORDER_TITLE.getCode(),
                MessageCardConstants.EnumerateValues.SHOP_WORK_ORDER_TITLE.getDefaultValue())
        );
        messageCardSendDTO.setLogo(dataDictionary.getOrDefault(
                MessageCardConstants.EnumerateValues.WORK_ORDER_CARD_ICON.getCode(),
                MessageCardConstants.EnumerateValues.WORK_ORDER_CARD_ICON.getDefaultValue())
        );
        messageCardSendDTO.setRedirectName(dataDictionary.getOrDefault(
                MessageCardConstants.EnumerateValues.REDIRECT_REVIEW_NAME.getCode(),
                MessageCardConstants.EnumerateValues.REDIRECT_REVIEW_NAME.getDefaultValue())
        );
        messageCardSendDTO.setRedirectUrl(webchatPageConfig.getMallShopReview());

        Map<String, String> varsParameter = new HashMap<>();
        varsParameter.put("logo", mallShop.getLogo());
        varsParameter.put("name", mallShop.getName());
        varsParameter.put("userName", submitUser.getUserName());
        varsParameter.put("dateTime", DateUtils.getDate2String(YYYY_MM_DD_HH_MM, new Date()));
        // 动态数据赋值
        dataDictionary.forEach((k, v) -> {
                    if (!varsParameter.containsKey(v)) {
                        return;
                    }
                    dataDictionary.put(k, varsParameter.get(v));
                }
        );

        /*
         *  已弃用，改为从数据字典中获取变量值
         Map<String, Object> vars = new HashMap<>();
         vars.put("k1", "店铺LOGO");
         vars.put("k2", "店铺名");
         vars.put("k3", "提交人");
         vars.put("k4", "提交时间");
         vars.put("v1", mallShop.getLogo());
         vars.put("v2", mallShop.getName());
         vars.put("v3", submitUser.getUserName());
         vars.put("v4", DateUtils.getDate2String(YYYY_MM_DD_HH_MM, new Date()));
         */
        // 渲染动态数据
        messageCardSendDTO.setVars((Map) dataDictionary);

        /**
         * MQ广播通知connect服务，完成服务号消息卡内容websocket主动推送
         */
        messageQueueProducer.broadSend(MessageBroadChannelEnum.QUEUE_MESSAGE_CARD_PUSH, messageCardSendDTO);
    }

    /**
     * 获取数据字典
     *
     * @param dataDictionaryCode 数据字典 编号
     * @return {@link Map }<{@link String }, {@link String }>
     */
    private Map<String, String> getDataDictionary(String dataDictionaryCode) {
        SysDataDictionaryBaseVO dataDictionaryBaseVO = sysDataDictionaryService.baseDetail(dataDictionaryCode);
        return sysDataDictionaryDetailService.detail(dataDictionaryBaseVO);
    }

}
